//--------------------------------------------------------------------------------------
// File: Tutorial06.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------


//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
Texture2D txDiffuse : register(t0);
SamplerState samLinear : register(s0);

cbuffer ConstantBuffer : register( b0 )
{
	matrix World;
	matrix View;
	matrix Projection;
	float4 vLightDir[2];
	float4 vLightColor[2];
	float4 vOutputColor;
}

struct Material 
{
	float Ka, Kd, Ks, A;
};

struct DirectionalLight
{
	float4 color;
	float3 dir;
};
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
    float4 Pos : POSITION;
	float3 Norm : NORMAL;
	float2 Tex : TEXCOORD0;
};

struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
	float3 Norm : NORMAL;
	float2 Tex : TEXCOORD0;
};



struct HS_CONSTANT_OUTPUT
{
	float edges[3]  : SV_TessFactor;
	float inside : SV_InsideTessFactor;
};

struct HS_OUTPUT
{
	float3 position  : POSITION;
};

struct DS_OUTPUT
{
	float4 position  : SV_POSITION;
	float4 color     : COLOR;
};

struct GS_INPUT
{
	float4 Pos : SV_POSITION;
	float3 Norm : NORMAL;
	float2 Tex : TEXCOORD0;
};



float4 calcPhongLighting(Material M, float4 LColor, float3 N, float3 L, float3 V, float3 R, float4 ambientLight)
{
		float4 Ia = M.Ka * ambientLight;
		float4 Id = M.Kd * saturate(dot(N, L));
		float4 Is = M.Ks * pow(saturate(dot(V, R)), M.A);

		return Ia + (Id + Is)*LColor;
}

//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------	
VS_OUTPUT VS( VS_INPUT input )
{
	VS_OUTPUT output = (VS_OUTPUT)0;
	//output.wp = mul(input.Pos, World);
	matrix mWorldViewProjection = mul(mul(World, View), Projection);
	output.Pos = mul(input.Pos, World);

	//output.Pos = mul(input.Pos, mWorldViewProjection);
	//output.Pos = mul(output.Pos, View);
	//output.Pos = mul(output.Pos, Projection);
	//output.Norm = mul(float4(input.Norm, 1), World).xyz;
	
	
	//output.Pos = input.Pos;
	output.Tex = input.Tex;

	return output;
}



HS_CONSTANT_OUTPUT HSConstant(InputPatch<VS_OUTPUT, 3> ip, uint pid : SV_PrimitiveID)
{
	HS_CONSTANT_OUTPUT output;

	float edge = 8.0f;
	float inside = 8.0f;

	output.edges[0] = edge;
	output.edges[1] = edge;
	output.edges[2] = edge;

	output.inside = inside;

	return output;
}


[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("HSConstant")]
HS_OUTPUT HS(InputPatch<VS_OUTPUT, 3> ip, uint cpid : SV_OutputControlPointID, uint pid : SV_PrimitiveID)
{
	HS_OUTPUT Output;
	Output.position = ip[cpid].Pos;

	//Output.position = mul(Output.position, Projection);
	//Output.position = mul(Output.position, View);
	//Output.position = mul(Output.position, Projection);

	return Output;
}

[domain("tri")]
DS_OUTPUT DS(HS_CONSTANT_OUTPUT input, float3 UV : SV_DomainLocation, const OutputPatch<HS_OUTPUT, 3> patch)
{
	DS_OUTPUT Output;
	
	float3 vWorldPos = UV.x * patch[0].position +
		UV.y * patch[1].position +
		UV.z * patch[2].position;

	//matrix mWorldViewProjection = mul(mul(Projection, View), World);
	//Output.position = mul(vWorldPos.xyz, World);
	//Output.position = mul(Output.position, View);
	//Output.position = mul(float4(vWorldPos.xyz, 1.0), World);
	//Output.position = mul(Output.position, View);
	//Output.position = mul(Output.position, Projection);
	//matrix mWorldViewProjection = mul(mul(World, View), Projection);
	Output.position = float4(vWorldPos.xyz, 1.0);

	//float3 topMidpoint = lerp(patch[0].position, patch[1].position, UV.x);
	//float3 bottomMidpoint = lerp(patch[1].position, patch[2].position, UV.x);

	//Output.position = float4(lerp(patch[0].position, patch[2].position, UV.y), 1);
	//Output.color = float4(UV.yx, 1 - UV.x, 1);
	//Output.color = float4(0.0, 1.0, 1.0, 0.0);
	/*
		Output.position = float4(patch[0].position.x, patch[1].position.x, patch[2].position.x, UV.x);
	*/
	//Output.position = mul(Output.position, World);
	//Output.position = mul(Output.position, View);
	//Output.position = mul(Output.position, Projection);
	
	return Output;
}











//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS_GLASS(DS_OUTPUT input) : SV_Target
{
	/*
	float4 finalColor = 0;

	float3 eye = float3(0.0f, 4.0f, -10.0f);
	float4 lightColor = vLightColor[1];
	float3 lightDir = (float3)vLightDir[1];
	float3 N = normalize(mul(input.Norm, (float3x3) World));
	float3 V = normalize(-eye);
	float3 R = reflect(lightDir, N);


	Material m;
	m.Ka = 0.5;
	m.Kd = 0.5;
	m.Ks = 0.8;
	m.A = 16;

	float4 l = calcPhongLighting(m, lightColor, N, lightDir, V, R, vOutputColor);

	finalColor = vOutputColor;
	finalColor += saturate(dot((float3)lightDir, input.Norm) * lightColor);

	finalColor.a = 1;
	

	return l * txDiffuse.Sample(samLinear, input.Tex);*/
	return float4(0.0,1.0,0.0,1.0);//vOutputColor;

}

float4 PS(DS_OUTPUT input) : SV_Target
{
	/*
	float4 finalColor = 0;

	float3 eye = float3(0.0f, 4.0f, -10.0f);
	float4 lightColor = vLightColor[1];
	float3 lightDir = (float3)vLightDir[1];
	float3 N = normalize(mul(input.Norm, (float3x3) World));
	float3 V = normalize(-eye);
	float3 R = reflect(lightDir, N);


	Material m;
	m.Ka = 0.5;
	m.Kd = 0.5;
	m.Ks = 0.8;
	m.A = 16;

	float4 l = calcPhongLighting(m, lightColor, N, lightDir, V, R, vOutputColor);

	finalColor = vOutputColor;
	finalColor += saturate(dot((float3)lightDir, input.Norm) * lightColor);
	
	finalColor.a = 1;
	

	return l * txDiffuse.Sample(samLinear, input.Tex);*/
	return float4(1.0, 0.0, 0.0, 1.0);
}


[maxvertexcount(12)]
void GSMain(triangle GS_INPUT input[3], inout LineStream<GS_INPUT> outputStream)
{
	/*GS_INPUT output;

	for (int i = 0; i < 3; ++i)
	{
		outputStream.Append(input[i]);
	}
	outputStream.RestartStrip();*/
}


//--------------------------------------------------------------------------------------
// PSSolid - render a solid color
//--------------------------------------------------------------------------------------
float4 PSSolid(DS_OUTPUT input) : SV_Target
{
	return float4(1.0, 0.0, 0.0, 1.0);;
}
